package me.sdevil507.org.service.impl;

import com.google.common.collect.Lists;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import me.sdevil507.biz.common.sysdict.po.SysDict;
import me.sdevil507.org.dto.OrgAllotResourcesParamsDto;
import me.sdevil507.org.dto.OrgResourceParamsDto;
import me.sdevil507.org.mapper.OrgResourceMapper;
import me.sdevil507.org.po.*;
import me.sdevil507.org.repository.OrgRepository;
import me.sdevil507.org.repository.OrgResourceRepository;
import me.sdevil507.org.repository.OrgRoleRepository;
import me.sdevil507.org.service.OrgResourceService;
import me.sdevil507.org.service.OrgRoleService;
import me.sdevil507.platform.po.PlatResourcePo;
import me.sdevil507.platform.repository.PlatResourceRepository;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.status.ComConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 机构资源表[OrgResourceServiceImpl]
 *
 * @author sdevil507
 * created on 2020-06-23 18:43:30
 */
@Service
public class OrgResourceServiceImpl implements OrgResourceService {

    @Resource
    private OrgRepository orgPoRepository;

    @Resource
    private OrgResourceRepository orgResourceRepository;
    @Resource
    private PlatResourceRepository platResourceRepository;

    @Autowired
    private OrgRoleRepository orgRoleRepository;

    @Autowired
    private OrgResourceMapper orgResourceMapper;

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Override
    public List<OrgResourcePo> readAll() {
        QOrgResourcePo qOrgResourcePo = QOrgResourcePo.orgResourcePo;

        // 开启谓语查询条件
        Predicate predicate = qOrgResourcePo.id.isNotNull()
                .and(qOrgResourcePo.parentId.isNull());
        // 排序
        Sort sort = Sort.by(new Sort.Order(Sort.Direction.ASC, "sortNum"));
        // 执行Iterable转换List
        return Lists.newArrayList(orgResourceRepository.findAll(predicate, sort).iterator());

    }

    @Override
    public List<PlatResourcePo> readOrgAllModule() {
        OrgPo orgPo = orgPoRepository.findById(OrgAccountHelper.getOrgId()).orElse(null);
        if (orgPo != null) {
            return new ArrayList<>(orgPo.getResources());
        }
        return null;
    }

    @Override
    public Page<OrgResourcePo> readAllByPage(OrgResourceParamsDto searchParamsDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QOrgResourcePo qOrgResourcePo = QOrgResourcePo.orgResourcePo;

        // 开启谓语查询条件
        Predicate predicate = qOrgResourcePo.id.isNotNull()
                .and(qOrgResourcePo.parentId.eq(searchParamsDto.getParentId()));

        String title = searchParamsDto.getTitle();
        if (!StringUtils.isEmpty(title)) {
            predicate = ExpressionUtils.and(predicate, qOrgResourcePo.title.like("%" + title + "%"));
        }

        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.ASC, "sortNum"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);
        return orgResourceRepository.findAll(predicate, pageable);
    }

    @Override
    public void create(OrgResourceParamsDto dto) {
        orgResourceRepository.save(orgResourceMapper.dto2po(dto));
    }

    @Override
    public void update(OrgResourceParamsDto dto) {
        OrgResourcePo po = orgResourceRepository.findById(dto.getId()).orElse(null);
        if (null != po) {
            orgResourceMapper.updatePoFromDto(dto, po);
            orgResourceRepository.save(po);
            //如果是增值模块，子都修改为增值模块
            if(dto.getClassify() == 2){
                this.updateSubModule(po, 2);
            }
        }
    }

    private void updateSubModule(OrgResourcePo po, int classify){
        List<OrgResourcePo> children = po.getChildren();
        if(!CollectionUtils.isEmpty(children)){
            children.forEach(orgResourcePo -> {
                orgResourcePo.setClassify(classify);
                orgResourceRepository.save(orgResourcePo);
                updateSubModule(orgResourcePo, classify);
            });
        }
        List<OrgResourcePo> subModules = po.getSubModules();
        if(!CollectionUtils.isEmpty(subModules)) {
            subModules.forEach(orgResourcePo -> {
                orgResourcePo.setClassify(classify);
                orgResourceRepository.save(orgResourcePo);
                updateSubModule(orgResourcePo, classify);
            });
        }
    }

    @Override
    public void delete(OrgResourceParamsDto dto) {
        orgResourceRepository.deleteById(dto.getId());
    }

    @Override
    public String getModuleCode(Long parentId) {
        List<OrgResourcePo> resourcePos = orgResourceRepository.findAllByParentIdOrderByCodeDesc(parentId);
        if (null != resourcePos && !resourcePos.isEmpty()) {
            // 如果同级有元素情况下
            String srcCode = resourcePos.get(0).getCode();
            String prefixStr = srcCode.substring(0, srcCode.length() - 2);
            String tempValStr = srcCode.substring(srcCode.length() - 2);
            return prefixStr + String.format("%02d", Integer.parseInt(tempValStr) + 1);
        } else {
            // 如果同级没有元素情况下
            OrgResourcePo orgResourcePo = orgResourceRepository.findById(parentId).orElse(null);
            if (orgResourcePo != null) {
                return orgResourcePo.getCode() + String.format("%02d", 1);
            }
            return null;
        }
    }

    @Override
    public List<OrgResourcePo> readAllWithBtnByModuleClassify(OrgResourceParamsDto dto) {
        QOrgResourcePo qOrgResourcePo = QOrgResourcePo.orgResourcePo;

        // 开启谓语查询条件
        Predicate predicate = qOrgResourcePo.id.isNotNull().and(qOrgResourcePo.parentId.isNull());

        List<OrgResourcePo> resourceList = jpaQueryFactory.selectFrom(qOrgResourcePo).where(predicate).fetch().stream()
                .filter(orgResourcePo -> orgResourcePo.getClassify().equals(dto.getClassify()))
                .collect(Collectors.toList());

        return resourceList;
    }

    @Override
    public List<PlatResourcePo> readResourcesByOrgIdList(List<Long> orgIdList, Integer moduleClassify) {
        //多个机构授权的模块都是一样的，取一个就行
        OrgPo orgPo = orgPoRepository.findById(orgIdList.get(0)).orElse(null);
        if(ComConstant.ModuleClassify.BASIC_MODULE.equals(moduleClassify)){
            //基础按钮（页面只展现了基础按钮）
            if(!CollectionUtils.isEmpty(orgIdList)){
                if (orgPo != null) {
                    return orgPo.getResources().stream()
                            .filter(orgResourcePo -> ComConstant.ModuleClassify.BASIC_MODULE.equals(orgResourcePo.getClassify()))
                            .collect(Collectors.toList());
                }
            }
        }else if(ComConstant.ModuleClassify.VALUE_MODULE.equals(moduleClassify)){
            //增值取全部（页面展现了全部按钮）
            if (orgPo != null) {
                return new ArrayList<>(orgPo.getResources());
            }
        }
        return null;
    }

    @Override
    public void allotResourcesOfOrgIdList(OrgAllotResourcesParamsDto dto) {
        List<Long> orgIdList = dto.getOrgIdList();
        List<String> resourceCodes = dto.getResourceCodes();
        // 查询出资源列表
        Set<PlatResourcePo> resources = platResourceRepository.findAllByCodeIn(resourceCodes);
        orgIdList.forEach(orgId -> {
            OrgPo orgPo = orgPoRepository.getOne(orgId);
            orgPo.setResources(resources);
            orgPoRepository.save(orgPo);
            System.out.println("=====已授权机构===" + orgPo.getNameZh());
            //获取管理员角色
            OrgUserPo orgMgrUserPo = orgPo.getPresetMgr();
            List<Long> mgrRoleIdList = new ArrayList<>();
            if(orgMgrUserPo != null){
                Set<OrgRolePo> mgrRoleSets = orgMgrUserPo.getRoles();
                mgrRoleIdList = mgrRoleSets.stream().map(OrgRolePo::getId).collect(Collectors.toList());
            }

            Set<OrgRolePo> roleList = orgPo.getRoles();
            for (OrgRolePo orgRolePo : roleList) {
                boolean isMgrRole = false;
                //判断是否是管理员角色，默认全部添加该资源
                if(!CollectionUtils.isEmpty(mgrRoleIdList)){
                    if(mgrRoleIdList.contains(orgRolePo.getId())){
                        isMgrRole = true;
                    }
                }
                Set<PlatResourcePo> filterBasicList;
                //不是管理员  取交集
                if(!isMgrRole){
                    //已有基础模块
                    Set<PlatResourcePo> orgBasicResource = orgResourceRepository.getOrgValueResourceRel(orgRolePo.getId(), ComConstant.ModuleClassify.BASIC_MODULE);
                    //和新授权的基础模块  求交集
                    filterBasicList = resources.stream()
                            .filter(orgResourcePo -> orgResourcePo.getClassify().equals(ComConstant.ModuleClassify.BASIC_MODULE))
                            .filter(item -> orgBasicResource.stream().map(PlatResourcePo::getId).collect(Collectors.toList()).contains(item.getId()))
                            .collect(Collectors.toSet());
                }else{
                    filterBasicList = resources;
                }
                //已有增值模块
                Set<PlatResourcePo> orgValueResource = orgResourceRepository.getOrgValueResourceRel(orgRolePo.getId(), ComConstant.ModuleClassify.VALUE_MODULE);

                if(dto.getModuleClassify().equals(ComConstant.ModuleClassify.BASIC_MODULE)) {
                    //批量授权按钮菜单 处理角色已授权冗余数据
                    //合并新授权的基础按钮  和 已有增值按钮 （此授权窗口只展现了基础按钮）
                    filterBasicList.addAll(orgValueResource);
                }else if(dto.getModuleClassify().equals(ComConstant.ModuleClassify.VALUE_MODULE)) {
                    //单个授权按钮菜单 处理角色已授权冗余数据
                    if(!isMgrRole){
                        //已有增值模块和新授权的增值模块 求交集 （此授权窗口展现了基础和增值按钮）
                        Set<PlatResourcePo> filterValueList = resources.stream()
                                .filter(orgResourcePo -> orgResourcePo.getClassify().equals(ComConstant.ModuleClassify.VALUE_MODULE))
                                .filter(item -> orgValueResource.stream().map(PlatResourcePo::getId).collect(Collectors.toList()).contains(item.getId()))
                                .collect(Collectors.toSet());
                        //合并新授权的基础按钮  和 增值按钮
                        filterBasicList.addAll(filterValueList);
                    }
                }
                //重新授权
//                orgRolePo.setResources(filterBasicList);
                orgRoleRepository.save(orgRolePo);
            };
        });
    }
}